#include "IIC.h"
//#include "stm32f4xx.h"                  // Device header

void I2C_Configuration(void){ //I2C初始化

		//开启GPIOB时钟
		RCC->AHB1ENR|=0x01<<1;
		//开启IIC时钟
		RCC->APB1ENR|=0x01<<21;
	
		//GPIO的初始化配置
		GPIOB->MODER&=~(0x02<<(8*2));
		GPIOB->MODER|=0x02<<(8*2);
		GPIOB->MODER&=~(0x02<<(9*2));
		GPIOB->MODER|=0x02<<(9*2);
	
		GPIOB->OTYPER|=0x01<<8;
		GPIOB->OTYPER|=0x01<<9;
		
		GPIOB->OSPEEDR&=~(0X03<<(8*2));
		GPIOB->OSPEEDR|=0X03<<(8*2);
	
		GPIOB->OSPEEDR&=~(0X03<<(9*2));
		GPIOB->OSPEEDR|=0X03<<(9*2);
	
		GPIOB->PUPDR&=~(0x0F<<(4*4));
		//引脚复用功能设置
		GPIOB->AFR[1]&=~(0xFF);
		GPIOB->AFR[1]|=0x04;
		GPIOB->AFR[1]|=(0x04<<(4));
		
		//IIC的初始化配置
		
		
		//选择IIC模式
		I2C1->CR1&=~(0x01<<1);
		//配置FREQ
		I2C1->CR2|=0x2A;
//		//选择是否为快速模式
//		I2C1->CCR|=0x01<<15;
//		I2C1->CCR&=0x01;
//		//选择快速模式占空比DUTY_CYCLE
//		I2C1->CCR|=0x01<<14;
//		I2C1->CCR&=0x00;
		//还差一个主机地址，第一位到第七位
		//这个地址与从器件地址不一样即可
		//I2C1->OAR1|=0x0A; 
		//配置CCR时钟频率
		I2C1->CCR|=0xFFF;
		I2C1->CCR&=0xD2;
		//配置上升时间
		I2C1->TRISE=I2C1->CR2+1; 
		//允许应答
		I2C1->CR1|=0x01<<10;
		//开启IIC
		I2C1->CR1|=0x01;
		
		
}

//void I2C_SEND_BUFFER(uint8_t SlaveAddr,uint8_t WriteAddr,uint8_t* pBuffer,uint16_t NumByteToWrite){ //I2C发送数据串（器件地址，内部地址，寄存器，数量）
//	//产生开始信号
//	I2C1->CR1|=0x01<<8;
//	while(!MY_CHECK_EVENT(0x0001,0x0003));//清除EV5
//	//因为是写，所以不用给地址加一
//	I2C1->DR=SlaveAddr;
//	while(!MY_CHECK_EVENT(0x0082,0x0007));//清除EV6
//	I2C1->DR = WriteAddr;
//	while(!MY_CHECK_EVENT(0x0084,0x0007));//清除EV8：移位寄存器非空，数据寄存器已空
//	while(NumByteToWrite--)
//	{
//		I2C1->DR = *pBuffer;
//		pBuffer++;
//		while(!MY_CHECK_EVENT(0x0084,0x0007));//清除EV8：移位寄存器非空，数据寄存器已空
//	}
//	//产生结束信号
//	I2C1->CR1|=0x01<<9;
//}

void I2C_SEND_BYTE(uint8_t SlaveAddr,uint8_t writeAddr,uint8_t pBuffer){ //I2C发送一个字节（从地址，内部地址，内容）	
	//产生开始信号
	I2C1->CR1|=0x01<<8;
	while(!MY_CHECK_EVENT(0x0001,0x0003));//清除EV5
	//因为是写，所以不用给地址加一
	I2C1->DR=SlaveAddr;
	while(!MY_CHECK_EVENT(0x0082,0x0007));//清除EV6
	//while(!MY_CHECK_EVENT(0x0084,0x0007));
	I2C1->DR = writeAddr;
	while(!MY_CHECK_EVENT(0x0084,0x0007));//清除EV8：移位寄存器非空，数据寄存器已空
	I2C1->DR = pBuffer;
	while(!MY_CHECK_EVENT(0x0084,0x0007));//清除EV8：移位寄存器非空，数据寄存器已空
	//产生结束信号
	I2C1->CR1|=0x01<<9;
}

//void I2C_READ_BUFFER(uint8_t SlaveAddr,uint8_t readAddr,uint8_t* pBuffer,uint16_t NumByteToRead){ //I2C读取数据串（器件地址，寄存器，内部地址，数量）
//	
//	//先判断总线是否忙碌
//	while((I2C1->SR2&0x02)==0x02);
//	//产生开始信号
//	I2C1->CR1|=0x01<<8;
//	while(!MY_CHECK_EVENT(0x0001,0x0003));//清除EV5
//	I2C1->DR=SlaveAddr;
//	while(!MY_CHECK_EVENT(0x0082,0x0007));//清除EV6
//	I2C1->DR=readAddr;
//	//上电
//	I2C1->CR1|=0x01;
//	while(!MY_CHECK_EVENT(0x0084,0x0007));//清除EV8
//	I2C1->CR1|=0x01<<8;//产生开始信号
//	while(!MY_CHECK_EVENT(0x0001,0x0003));
//	I2C1->DR=SlaveAddr+1;//传出地址信号，主机为读
//	while(!MY_CHECK_EVENT(0x0002,0x0003));//清除EV6
//	while(NumByteToRead)
//	{
//		if(NumByteToRead == 1){ //只剩下最后一个数据时进入 if 语句
//			//产生结束信号以及关闭应答
//			I2C1->CR1|=0x0001<<9;
//			I2C1->CR1&=0xFBFF;
//		}
//		while(!MY_CHECK_EVENT(0x0040,0x0003));
//		*pBuffer=I2C1->DR;
//		pBuffer++;
//		NumByteToRead--;
//	}
//	//开启应答,因为该位在PE为1的时候只能由软件置位，所以这里必须开启应答，否则下次使用该函数就没应答了
//	I2C1->CR1|=0x0001<<10;
//}

u8 I2C_READ_BYTE(uint8_t SlaveAddr,uint8_t readAddr){ //I2C读取一个字节
		
	uint8_t data;
	//产生开始信号
	
	I2C1->CR1|=0x01<<8;
	
	while(!MY_CHECK_EVENT(0x0001,0x0003));
	I2C1->DR=SlaveAddr;
	
	while(!MY_CHECK_EVENT(0x0082,0x0007));
	I2C1->DR=readAddr;
	
	while(!MY_CHECK_EVENT(0x0084,0x0007));
	//重新产生起始信号
	I2C1->CR1|=0x01<<8;
	while(!MY_CHECK_EVENT(0x0001,0x0003));
	//读数据,最后一位要为1
	I2C1->DR=SlaveAddr+1;
	while(!MY_CHECK_EVENT(0x0002,0x0003));
	
	//产生结束信号以及关闭应答
	I2C1->CR1|=0x0001<<9;
	I2C1->CR1&=0xFBFF;
	while(!MY_CHECK_EVENT(0x0040,0x0003));
	data=I2C1->DR;
	//开启应答
	I2C1->CR1|=0x0001<<10;
	return data;
}

uint8_t MY_CHECK_EVENT(uint16_t SR1,uint16_t SR2)
{
	//先读取SR1，只有ADDR被置位 或者STOPF被清除才可以读取SR2的值
	if( (I2C1->SR1&0x0002 ) || !(I2C1->SR1&0x0010) )
	{
		if( ( (I2C1->SR1 & SR1)==SR1 ) && ( (I2C1->SR2 & SR2)==SR2 ) )
			return 1;
		else
			return 0;
	}
	else
	{
		return 0;
	}
}













//while((I2C1->SR2&0x02)==0x02);判断忙碌
